package org.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.example.entity.AnnualLeave;
import org.example.entity.AttendanceRecord;
import org.example.entity.LeaveApplication;
import org.example.models.R;
import org.example.service.AnnualLeaveService;
import org.example.service.AttendanceRecordService;
import org.example.service.LeaveApplicationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Author: 鸢一折纸
 * @Email: 3498881048@qq.com
 * @Date: 2025/09/08 8:34
 * @Description:
 **/

@RestController
@RequestMapping("/leaveApplication")

public class LeaveApplicationController {

    @Autowired
    private LeaveApplicationService leaveApplicationService;
    @Autowired
    private AnnualLeaveService annualLeaveService;
    @Autowired
    private AttendanceRecordService attendanceRecordService;

    @GetMapping("/page")
    public R<Page<LeaveApplication>> page(
            @RequestParam(name = "current", defaultValue = "1") int current,
            @RequestParam(name = "size", defaultValue = "4") int size,
            @RequestParam(name = "userId", required = false) Integer userId,
            @RequestParam(name = "leaveType", required = false) String leaveType,
            @RequestParam(name = "attendanceCycle", required = false) String attendanceCycle,
            @RequestParam(name = "applicationDate", required = false) String applicationDate
    ) {
        Page<LeaveApplication> page = new Page<>(current, size);
        page = leaveApplicationService.findLeaveApplication(page, userId, leaveType, attendanceCycle, applicationDate);
        return R.success(page);
    }

    @GetMapping("/findAllAnnual")
    public R<List<String>> findAllAnnual(String leaveType, @RequestAttribute("userId") Integer userId) {

        return R.success(leaveApplicationService.findAllAnnual(leaveType, userId));
    }

    @GetMapping("/findByApplicationDate")
    public R<List<LeaveApplication>> findByApplicationDate(String createdAt, @RequestAttribute("userId") Integer userId) {
        QueryWrapper<LeaveApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("created_at", createdAt);
        return R.success(leaveApplicationService.list(queryWrapper));
    }

    @GetMapping("/findAnnualLeave")
    public R<List<LeaveApplication>> findAnnualLeave(String leaveDate, @RequestAttribute("userId") Integer userId) {
        QueryWrapper<LeaveApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("leave_date", leaveDate);
        return R.success(leaveApplicationService.list(queryWrapper));
    }

    @PostMapping("/insertBatch")
    public R<String> insertLeaveApplicationBatch(@RequestBody List<LeaveApplication> leaveApplications, @RequestAttribute("userId") Integer userId) {
        if (leaveApplications == null || leaveApplications.isEmpty()) {
            return R.error("请至少提交一条请假记录");
        }

        // 批量处理每条请假记录
        for (LeaveApplication leaveApplication : leaveApplications) {
            if (leaveApplication == null) continue;

            // 设置用户ID
            if (userId != null) {
                leaveApplication.setUserId(userId);
            }

            // 检查是否已存在相同日期和时段的请假申请
            if (isDuplicateLeaveApplication(leaveApplication, userId)) {
                return R.error("存在重复的请假申请");
            }

            if (!checkAttendanceStatus(leaveApplication, userId)) {
                return R.error("该日期已被占用，不可申请");
            }

            // 获取请假类型
            String leaveType = leaveApplication.getLeaveType();
            String leavePeriod = (String) leaveApplication.getLeavePeriod();

            // 设置开始时间和结束时间
            Date leaveDate = leaveApplication.getLeaveDate();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(leaveDate);

            Date startTime = null;
            Date endTime = null;

            if ("上午".equals(leavePeriod)) {
                calendar.set(Calendar.HOUR_OF_DAY, 8);
                calendar.set(Calendar.MINUTE, 0);
                startTime = calendar.getTime();

                calendar.set(Calendar.HOUR_OF_DAY, 12);
                calendar.set(Calendar.MINUTE, 0);
                endTime = calendar.getTime();
            } else if ("下午".equals(leavePeriod)) {
                calendar.set(Calendar.HOUR_OF_DAY, 12);
                calendar.set(Calendar.MINUTE, 0);
                startTime = calendar.getTime();

                calendar.set(Calendar.HOUR_OF_DAY, 18);
                calendar.set(Calendar.MINUTE, 0);
                endTime = calendar.getTime();
            } else if ("全天".equals(leavePeriod)) {
                calendar.set(Calendar.HOUR_OF_DAY, 8);
                calendar.set(Calendar.MINUTE, 0);
                startTime = calendar.getTime();

                calendar.set(Calendar.HOUR_OF_DAY, 18);
                calendar.set(Calendar.MINUTE, 0);
                endTime = calendar.getTime();
            }
            leaveApplication.setStartTime(startTime);
            leaveApplication.setEndTime(endTime);

            // 判断请假类型并处理
            if ("病假".equals(leaveType)) {
                boolean result = handleSickLeave(leaveApplication, userId);
                if (!result) {
                    return R.error("当前周期病假额度不足，请申请事假");
                }
            } else if ("事假".equals(leaveType)) {
                boolean result = handlePersonalLeave(leaveApplication, userId);
                if (!result) {
                    return R.error("事假处理失败");
                }
            } else if ("年假".equals(leaveType)) {
                boolean result = handleAnnualLeave(leaveApplication, userId);
                if (!result) {
                    return R.error("年假余额不足");
                }
            }

            // 保存请假申请
            boolean saveSuccess = leaveApplicationService.save(leaveApplication);
            if (!saveSuccess) {
                return R.error("请假申请失败");
            }

            // 更新考勤记录
            updateAttendanceRecords(leaveApplication);
        }

        return R.success("请假申请成功");
    }

    /**
     * 检查是否存在重复的请假申请
     */
    private boolean isDuplicateLeaveApplication(LeaveApplication leaveApplication, Integer userId) {
        QueryWrapper<LeaveApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .eq("leave_date", leaveApplication.getLeaveDate());

        // 如果是更新操作，需要排除当前记录本身
        if (leaveApplication.getLeaveId() != null) {
            queryWrapper.ne("leave_id", leaveApplication.getLeaveId());
        }

        List<LeaveApplication> existingApplications = leaveApplicationService.list(queryWrapper);

        String newPeriod = (String) leaveApplication.getLeavePeriod();

        for (LeaveApplication existing : existingApplications) {
            String existingPeriod = (String) existing.getLeavePeriod();

            // 检查完全相同的时段
            if (newPeriod.equals(existingPeriod)) {
                return true; // 相同时段重复
            }

            // 检查时段冲突
            if ("全天".equals(newPeriod) || "全天".equals(existingPeriod)) {
                return true; // 全天与任何时段都冲突
            }
        }

        return false;
    }

    /**
     * 检查考勤记录状态，只有未签到才能请假
     */
    private boolean checkAttendanceStatus(LeaveApplication leaveApplication, Integer userId) {
        // 获取请假日期和时段
        Date leaveDate = leaveApplication.getLeaveDate();
        String leavePeriod = (String) leaveApplication.getLeavePeriod();

        // 查询考勤记录
        QueryWrapper<AttendanceRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId)
                .eq("record_date", leaveDate);

        AttendanceRecord record = attendanceRecordService.getOne(wrapper);
        if (record == null) {
            // 如果没有考勤记录，默认允许请假
            return true;
        }

        // 检查对应时段是否为未签到状态
        if ("上午".equals(leavePeriod)) {
            return "未签到".equals(record.getMorningStatus()) || record.getMorningStatus() == null;
        } else if ("下午".equals(leavePeriod)) {
            return "未签到".equals(record.getAfternoonStatus()) || record.getAfternoonStatus() == null;
        } else if ("全天".equals(leavePeriod)) {
            return ("未签到".equals(record.getMorningStatus()) || record.getMorningStatus() == null) &&
                    ("未签到".equals(record.getAfternoonStatus()) || record.getAfternoonStatus() == null);
        }

        return false;
    }


    /**
     * 处理病假申请，每月最多4天
     */
    private boolean handleSickLeave(LeaveApplication leaveApplication, Integer userId) {
        List<LeaveApplication> existingSickLeaves = leaveApplicationService.list(new QueryWrapper<LeaveApplication>()
                .eq("user_id", userId)
                .eq("leave_type", "病假")
                .apply("DATE_FORMAT(application_date, '%Y-%m') = DATE_FORMAT({0}, '%Y-%m')", leaveApplication.getApplicationDate()));

        double totalSickDays = existingSickLeaves.stream()
                .mapToDouble(l -> l.getDuration() != null ? l.getDuration().doubleValue() : 0)
                .sum();

        double newDays = leaveApplication.getDuration() != null ? leaveApplication.getDuration().doubleValue() : 0;

        if (totalSickDays + newDays > 4) {
            // 超出额度，提示转为事假
            return false;
        }

        return true;
    }

    /**
     * 处理事假申请，优先使用年假余额
     */
    private boolean handlePersonalLeave(LeaveApplication leaveApplication, Integer userId) {
        // 查询当前年度年假余额
        AnnualLeave annualLeave = annualLeaveService.getOne(new QueryWrapper<AnnualLeave>()
                .eq("user_id", userId)
                .eq("annual_cycle", getYearCycle(leaveApplication.getApplicationDate())));

        if (annualLeave != null && annualLeave.getSurplusDate() > 0) {
            // 获取需要消耗的天数
            double requiredDays = leaveApplication.getDuration() != null ? leaveApplication.getDuration().doubleValue() : 0;

            // 如果年假余额足够
            if (annualLeave.getSurplusDate() >= requiredDays) {
                // 消耗年假余额
                int useDays = (int) requiredDays;
                annualLeave.setUseDate(annualLeave.getUseDate() + useDays);
                annualLeave.setSurplusDate(annualLeave.getSurplusDate() - useDays);
                annualLeaveService.updateById(annualLeave);

                // 设置年假ID到请假申请记录中
                leaveApplication.setAnnualId(annualLeave.getAnnualId());

                return true;
            } else {
                // 年假余额不足，消耗完所有年假余额
                Double useDays = annualLeave.getSurplusDate();
                annualLeave.setUseDate(annualLeave.getUseDate() + useDays);
                annualLeave.setSurplusDate(0.0);
                annualLeaveService.updateById(annualLeave);

                // 设置年假ID到请假申请记录中
                leaveApplication.setAnnualId(annualLeave.getAnnualId());

                return true;
            }
        }

        // 没有年假余额，完全作为事假处理
        return true;
    }

    /**
     * 处理年假申请，从当前年份开始向前查找剩余余额
     */
    private boolean handleAnnualLeave(LeaveApplication leaveApplication, Integer userId) {
        double requiredDays = leaveApplication.getDuration() != null ? leaveApplication.getDuration().doubleValue() : 0;
        double remainingDays = requiredDays; // 还需要扣除的天数

        // 从当前年份开始向前查找
        String currentCycle = getYearCycle(leaveApplication.getApplicationDate());

        // 添加空值检查
        if (currentCycle == null || currentCycle.trim().isEmpty()) {
            return false; // 或者抛出自定义异常
        }

        for (int year = Integer.parseInt(currentCycle); year >= 2020 && remainingDays > 0; year--) {
            String cycle = String.valueOf(year);
            AnnualLeave annualLeave = annualLeaveService.getOne(new QueryWrapper<AnnualLeave>()
                    .eq("user_id", userId)
                    .eq("annual_cycle", cycle));

            if (annualLeave == null || annualLeave.getSurplusDate() <= 0) continue;

            // 判断当前年假余额是否足够
            if (annualLeave.getSurplusDate() >= remainingDays) {
                // 当前年假余额足够，扣除所需天数
                annualLeave.setUseDate(annualLeave.getUseDate() + remainingDays);
                annualLeave.setSurplusDate(annualLeave.getSurplusDate() - remainingDays);
                annualLeaveService.updateById(annualLeave);

                // 设置年假ID到请假申请记录中（设置为最后一个使用的年假ID）
                leaveApplication.setAnnualId(annualLeave.getAnnualId());

                remainingDays = 0; // 已经扣完所需天数
            } else {
                // 当前年假余额不足，消耗完当前年假余额
                remainingDays -= annualLeave.getSurplusDate();
                annualLeave.setUseDate(annualLeave.getUseDate() + annualLeave.getSurplusDate());
                annualLeave.setSurplusDate(0.0);
                annualLeaveService.updateById(annualLeave);

                // 设置年假ID到请假申请记录中（设置为最后一个使用的年假ID）
                leaveApplication.setAnnualId(annualLeave.getAnnualId());
            }
        }

        // 如果还有剩余天数未扣除，说明年假余额不足
        return remainingDays == 0;
    }

    /**
     * 根据年份获取年周期
     */
    private String getYearCycle(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        return sdf.format(date);
    }

    /**
     * 更新考勤记录
     */
    private void updateAttendanceRecords(LeaveApplication leaveApplication) {
        // 获取请假日期和时段
        Date leaveDate = leaveApplication.getLeaveDate();
        String leavePeriod = (String) leaveApplication.getLeavePeriod();

        // 设置开始时间和结束时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(leaveDate);

        // 更新考勤记录
        QueryWrapper<AttendanceRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", leaveApplication.getUserId())
                .eq("record_date", leaveDate);

        AttendanceRecord record = attendanceRecordService.getOne(wrapper);
        if (record == null) return;

        if ("上午".equals(leavePeriod)) {
            record.setMorningStatus("请假");
        } else if ("下午".equals(leavePeriod)) {
            record.setAfternoonStatus("请假");
        } else if ("全天".equals(leavePeriod)) {
            record.setMorningStatus("请假");
            record.setAfternoonStatus("请假");
        }

        attendanceRecordService.updateById(record);
    }


}
